package org.opens.mybatisplus.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.opens.mybatisplus.pojo.dto.MyBatisPerson;

import java.util.List;
import java.util.Map;
import java.util.Optional;

@Mapper
public interface MyBatisPersonDao extends BaseMapper<MyBatisPerson> {

    public List<MyBatisPerson> findByPage(
            @Param(value = "start") int start,
            @Param(value = "end") int end
    );

    @Select("select id, name_value, old, ek_address from mybatis_person where id = #{id}")
    public MyBatisPerson findById(@Param(value = "id") int id);

    @Insert("insert into mybatis_person(id, name_value, old, ek_address) values(#{id}, #{nameValue}, #{old}, #{ekAddress})")
    public Integer save(MyBatisPerson myBatisPerson);

    public List<MyBatisPerson> findEqIdAndEqOldAndLikeName(@Param(value = "id") int id, @Param(value = "old") int old, @Param(value = "name") String name);

    public List<MyBatisPerson> findChooseEqIdOrChooseLikeName(@Param(value = "id") Integer id, @Param(value = "name") String name);

    public int update(MyBatisPerson person);


    /*@Update({
            "<script>update mybatis_person"                                 ,
            "        <set>"                                                 ,
            "            <if test='old > 0'>"                               ,
            "                old = #{old},"                                 ,
            "            </if>"                                             ,
            "            <if test='ekAddress != null and ekAddress != '''>" ,
            "                ek_address = #{ekAddress},"                    ,
            "            </if>"                                             ,
            "            <if test='nameValue != null and nameValue != '''>" ,
            "                name_value = #{nameValue}"                     ,
            "            </if>"                                             ,
            "        </set>"                                                ,
            "        where id = #{id}"                                      ,
            "</script>"
    })//mybatis的注解实现并不是很好用
    public int updateUseScript(MyBatisPerson person);*/

    @Select(value = "select count(*) as total from mybatis_person")
    public MyBatisPerson.Count2 countAll2();

    /**
     * 功能:
     *      使用foreach标签进行批量插入.
     * @param list  多个数据
     * @return      插入的行数
     */
    public int insertToList(List<MyBatisPerson> list);

    /**
     * 功能:
     *      使用Map作为参数类型.
     * @param map   参数类型
     * @return      受影响行数
     */
    public int insertToMap(@Param(value = "map") Map<String, Object> map);

    /**
     * 功能:
     *      使用foreach标签来实现遍历集合, 模拟in查询.
     * @param ids   多个id的集合.
     * @return      根据多个id进行in查询的结果.
     */
    public List<MyBatisPerson> findByIds(@Param(value = "ids_list") List<Integer> ids);

    @Select(value = "select count(*) as count from mybatis_person")
    public MyBatisPerson.Count countAll();

    @Select("select id, name_value, old, ek_address from mybatis_person")
    public List<MyBatisPerson> findAll();

    /**
     * 功能:
     *      测试返回结果为Map会怎么样.
     * 输出:
     *      org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 13
     * 说明:
     *      1. 可以发现, 一个Map只能容纳一行记录; 所以如果返回多行记录, 应该返回List<HashMap<K, V>>
     *
     */
    public Map<Integer, Integer> getMap();

    /**
     * 功能:
     *     将dao层的返回值直接封装为Optional.
     */
    @Select(value = "select id, name_value, old, ek_address from mybatis_person where id = #{id}")
    public Optional<MyBatisPerson> getOneUseId(@Param(value = "id") int id);

    /**
     * 功能:
     *      测试将List这样的结果封装为Optional.
     * 结果:
     *      1. 如果将多个返回值的sql的结果封装为Optional, 会报错: `Caused by: org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3`,
     *          - 从报错信息上看, 使用Optional封装结果集时, 底层会使用selectOne方法.
     *      2. 在将结果取出Optional封装之后, 不报错了, 说明dao层结果不能直接封装为List.
     */
    @Select(value = "select id, name_value, old, ek_address from mybatis_person where FIND_IN_SET(id, #{ids})")
    public Optional<List<MyBatisPerson>> getList(@Param(value = "ids") String ids);

    public Integer insertAndReturnId(@Param(value = "myBatisPerson") MyBatisPerson myBatisPerson);

    /**
     * 功能:
     *      使用mysql的ON DUPLICATE KEY UPDATE语法实现批量更新.
     * 注意:
     *      1. ON DUPLICATE KEY UPDATE是mysql独有的语法, 其他数据库没有这个操作.
     */
    public void batchUpdate(@Param(value = "personList") List<MyBatisPerson> list);

    public void batchUpdate2(@Param(value = "personList") List<MyBatisPerson> list);

    public List<MyBatisPerson> useTrimQuery(@Param(value = "person") MyBatisPerson myBatisPerson);

    public List<MyBatisPerson> useBindQuery(@Param(value = "person") MyBatisPerson myBatisPerson);

    public void deleteById(@Param(value = "id") Integer id);

    public List<MyBatisPerson> pageOfConditions(@Param(value = "person") MyBatisPerson myBatisPerson);

    public IPage<MyBatisPerson> pageOfConditions(Page<MyBatisPerson> page, @Param(value = "person") MyBatisPerson person);

}
